home *** CD-ROM | disk | FTP | other *** search
/ Aminet 40 / Aminet 40 (2000)(Schatztruhe)[!][Dec 2000].iso / Aminet / comm / tcp / Amster.lha / Amster_Install / Source / share.c < prev    next >
C/C++ Source or Header  |  2000-07-20  |  31KB  |  1,201 lines

  1. /*
  2. ** Amster - File sharing
  3. ** by Jacob Laursen <laursen@myself.com>
  4. */
  5.  
  6. #include "include/config.h"
  7.  
  8. #include <stdio.h>
  9. #include <stdlib.h>
  10. #include <string.h>
  11.  
  12. #include "include/mui.h"
  13. #include <MUI/NListview_mcc.h>
  14.  
  15. #include <proto/asl.h>
  16. #include <proto/dos.h>
  17.  
  18. #include <libraries/asl.h>
  19. #include <libraries/dos.h>
  20.  
  21. #include <exec/memory.h>
  22. #include <dos/exall.h>
  23. #include <utility/tagitem.h>
  24. #include <workbench/workbench.h>
  25.  
  26. #include "md5.h"
  27. #include "include/protos.h"
  28. #include "include/gui.h"
  29. #include "include/info.h"
  30. #include "include/share.h"
  31. #include "include/prefs.h"
  32. #include "include/panel.h"
  33. #include "include/napster.h"
  34. #include "include/upload.h"
  35. #include "include/rexx.h"
  36. #include "amster_Cat.h"
  37.  
  38.  
  39. unsigned int numsongs=0, numbytes=0;
  40. BOOL sharechanged=FALSE, sharefailed=FALSE;
  41.  
  42. struct FileRequester *FReqAddFiles;
  43. struct FileRequester *FReqAddDir;
  44. struct FileRequester *FReqLibrary;
  45.  
  46.  
  47. MUIF share_dispatch(REG(a0) struct IClass *cl, REG(a2) Object *obj, REG(a1) Msg msg)
  48. {
  49.     struct shdata *data;
  50.  
  51.     switch(msg->MethodID) {
  52.         case OM_NEW:
  53.             return(share_new(cl, obj, (APTR)msg));
  54.         case OM_DISPOSE:
  55.             if (FReqAddFiles) FreeAslRequest(FReqAddFiles);
  56.             if (FReqAddDir)   FreeAslRequest(FReqAddDir);
  57.             if (FReqLibrary)  FreeAslRequest(FReqLibrary);
  58.             break;
  59.         case SHARE_OPEN:
  60.             data = INST_DATA(cl, obj);
  61.             update_stat(data);
  62.             set(obj, MUIA_Window_Open, TRUE);
  63.             return NULL;
  64.         case SHARE_CLOSE:
  65.             set(obj, MUIA_Window_Open, FALSE);
  66.             return NULL;
  67.         case SHARE_ADD:
  68.             data = INST_DATA(cl, obj);
  69.             add_shares(data);
  70.             return NULL;
  71.         case SHARE_ADDDIR:
  72.             data = INST_DATA(cl, obj);
  73.             add_directory(data);
  74.             return NULL;
  75.         case SHARE_REMOVE:
  76.             data = INST_DATA(cl, obj);
  77.             remove_shares(data, (long)(((muimsg)msg)->arg1));
  78.             return NULL;
  79.         case SHARE_SAVE:
  80.             data = INST_DATA(cl, obj);
  81.             save_shares(data);
  82.             return NULL;
  83.         case SHARE_SAVEAS:
  84.             data = INST_DATA(cl, obj);
  85.             save_shares_as(data);
  86.             return NULL;
  87.         case SHARE_LOAD:
  88.             data = INST_DATA(cl, obj);
  89.             load_shares(data);
  90.             return NULL;
  91.         case SHARE_LOADAS:
  92.             data = INST_DATA(cl, obj);
  93.             load_shares_as(data);
  94.             return NULL;
  95.         case SHARE_UPLOAD:
  96.             data = INST_DATA(cl, obj);
  97.             upload_file_confirm(data, (char *)(((muimsg)msg)->arg1), (char *)(((muimsg)msg)->arg2));
  98.             return NULL;
  99.         case SHARE_NOTIFYALL:
  100.             data = INST_DATA(cl, obj);
  101.             notify_shares(data);
  102.             return NULL;
  103.         case SHARE_PLAY:
  104.             data = INST_DATA(cl, obj);
  105.             play_share(data);
  106.             return NULL;
  107.         case SHARE_ADDFILE:
  108.             data = INST_DATA(cl, obj);
  109.             add_file(data, (song)(((muimsg)msg)->arg1), (char *)(((muimsg)msg)->arg2));
  110.             return NULL;
  111.         case SHARE_ADDFILEN:
  112.             data = INST_DATA(cl, obj);
  113.             add_filename(data, (char *)(((muimsg)msg)->arg1));
  114.             return NULL;
  115.         case SHARE_SETDIR:
  116.             strcpy(FReqAddFiles->fr_Drawer, (char *)(((muimsg)msg)->arg1));
  117.             strcpy(FReqAddDir->fr_Drawer, (char *)(((muimsg)msg)->arg1));
  118.             return NULL;
  119.         case SHARE_UPDCOUNT:
  120.             data = INST_DATA(cl, obj);
  121.             update_count(data, (char *)(((muimsg)msg)->arg1));
  122.             return NULL;
  123.     }
  124.     return(DoSuperMethodA(cl, obj, msg));
  125. }
  126.  
  127.  
  128. MUIF sharelistdest(REG(a2) APTR pool, REG(a1) sharedata sd)
  129. {
  130.     char *path;
  131.  
  132.     numsongs--;
  133.     numbytes -= sd->size;
  134.     if (gui_onlinestate == ONLINE) {
  135.         path = MakeWinPath(sd->title);
  136.         nap_sendbuf(NAPC_REMOVESHARE, path);
  137.         free(path);
  138.     }
  139.     free(sd);
  140.  
  141.     return(0);
  142. }
  143.  
  144.  
  145. MUIF sharelistdisp(REG(a2) char **array, REG(a1) sharedata sd)
  146. {
  147.     static char size[16], md5[33], time[20], bitrate[16], freq[16], count[16];
  148.  
  149.     if (sd) {
  150.             *array++ = sd->title;
  151.             sprintf(size, "\33r%ld", sd->size);
  152.             *array++ = size;
  153.             sprintf(time, "\33r%ld:%02ld", sd->time/60, sd->time%60);
  154.             *array++ = time;
  155.             sprintf(bitrate, "\33r%ld", sd->bitrate);
  156.             *array++ = bitrate;
  157.             sprintf(freq, "\33l%ld", sd->freq);
  158.             *array++ = freq;
  159.             sprintf(count, "\33r%ld", sd->reqcount);
  160.             *array++ = count;
  161.             strcpy(md5, sd->md5);
  162.             *array = md5;
  163.     } else {
  164.         *array++ = (char *)MSG_LH_FILE;
  165.         *array++ = (char *)MSG_LH_SIZE;
  166.         *array++ = (char *)MSG_LH_TIME;
  167.         *array++ = (char *)MSG_LH_BITRATE;
  168.         *array++ = (char *)MSG_LH_FREQ;
  169.         *array++ = (char *)MSG_LH_COUNT;
  170.         *array   = (char *)MSG_LH_CHECKSUM;
  171.     }
  172.     return(0);
  173. }
  174.  
  175.  
  176. MUIF sharelistcomp(REG(a0) struct Hook *hook, REG(a2) Object *obj, REG(a1) struct NList_CompareMessage *ncm)
  177. {
  178.     sharedata entry1 = ncm->entry1;
  179.     sharedata entry2 = ncm->entry2;
  180.     LONG col1 = ncm->sort_type & MUIV_NList_TitleMark_ColMask;
  181.     LONG col2 = ncm->sort_type2 & MUIV_NList_TitleMark2_ColMask;
  182.     ULONG result = 0;
  183.  
  184.     if (ncm->sort_type == MUIV_NList_SortType_None) return (0);
  185.  
  186.     if (col1 == 0) {
  187.         if (ncm->sort_type & MUIV_NList_TitleMark_TypeMask)
  188.             result = (LONG) stricmp(entry2->title, entry1->title);
  189.         else
  190.             result = (LONG) stricmp(entry1->title, entry2->title);
  191.     }
  192.     else if (col1 == 1) {
  193.         if (ncm->sort_type & MUIV_NList_TitleMark_TypeMask)
  194.             result = entry2->size - entry1->size;
  195.         else
  196.             result = entry1->size - entry2->size;
  197.     }
  198.     else if (col1 == 2) {
  199.         if (ncm->sort_type & MUIV_NList_TitleMark_TypeMask)
  200.             result = entry2->time - entry1->time;
  201.         else
  202.             result = entry1->time - entry2->time;
  203.     }
  204.     else if (col1 == 3) {
  205.         if (ncm->sort_type & MUIV_NList_TitleMark_TypeMask)
  206.             result = entry2->bitrate - entry1->bitrate;
  207.         else
  208.             result = entry1->bitrate - entry2->bitrate;
  209.     }
  210.     else if (col1 == 4) {
  211.         if (ncm->sort_type & MUIV_NList_TitleMark_TypeMask)
  212.             result = entry2->freq - entry1->freq;
  213.         else
  214.             result = entry1->freq - entry2->freq;
  215.     }
  216.     else if (col1 == 5) {
  217.         if (ncm->sort_type & MUIV_NList_TitleMark_TypeMask)
  218.             result = entry2->reqcount - entry1->reqcount;
  219.         else
  220.             result = entry1->reqcount - entry2->reqcount;
  221.     }
  222.     else if (col1 == 6) {
  223.         if (ncm->sort_type & MUIV_NList_TitleMark_TypeMask)
  224.             result = (LONG) stricmp(entry2->md5, entry1->md5);
  225.         else
  226.             result = (LONG) stricmp(entry1->md5, entry2->md5);
  227.     }
  228.  
  229.     if ((result != 0) || (col1 == col2)) return (result);
  230.  
  231.     if (col2 == 0) {
  232.         if (ncm->sort_type & MUIV_NList_TitleMark2_TypeMask)
  233.             result = (LONG) stricmp(entry2->title, entry1->title);
  234.         else
  235.             result = (LONG) stricmp(entry1->title, entry2->title);
  236.     }
  237.     else if (col2 == 1) {
  238.         if (ncm->sort_type & MUIV_NList_TitleMark2_TypeMask)
  239.             result = entry2->size - entry1->size;
  240.         else
  241.             result = entry1->size - entry2->size;
  242.     }
  243.     else if (col2 == 2) {
  244.         if (ncm->sort_type & MUIV_NList_TitleMark2_TypeMask)
  245.             result = entry2->time - entry1->time;
  246.         else
  247.             result = entry1->time - entry2->time;
  248.     }
  249.     else if (col2 == 3) {
  250.         if (ncm->sort_type & MUIV_NList_TitleMark2_TypeMask)
  251.             result = entry2->bitrate - entry1->bitrate;
  252.         else
  253.             result = entry1->bitrate - entry2->bitrate;
  254.     }
  255.     else if (col2 == 4) {
  256.         if (ncm->sort_type & MUIV_NList_TitleMark2_TypeMask)
  257.             result = entry2->freq - entry1->freq;
  258.         else
  259.             result = entry1->freq - entry2->freq;
  260.     }
  261.     else if (col2 == 5) {
  262.         if (ncm->sort_type & MUIV_NList_TitleMark2_TypeMask)
  263.             result = entry2->reqcount - entry1->reqcount;
  264.         else
  265.             result = entry1->reqcount - entry2->reqcount;
  266.     }
  267.     else if (col2 == 6) {
  268.         if (ncm->sort_type & MUIV_NList_TitleMark2_TypeMask)
  269.             result = (LONG) stricmp(entry2->md5, entry1->md5);
  270.         else
  271.             result = (LONG) stricmp(entry1->md5, entry2->md5);
  272.     }
  273.  
  274.     return (result);
  275. }
  276.  
  277.  
  278. MUIF ShareListAppMsgFunc(REG(a2) APTR obj, REG(a1) struct AppMessage **x)
  279. {
  280.     struct WBArg *ap;
  281.     struct AppMessage *amsg = *x;
  282.     int i;
  283.     static char buf[256];
  284.  
  285.     for (ap=amsg->am_ArgList, i=0; i<amsg->am_NumArgs; i++, ap++)
  286.     {
  287.         NameFromLock(ap->wa_Lock, buf, sizeof(buf));
  288.         AddPart(buf, ap->wa_Name, sizeof(buf));
  289.         DoMethod(gui->shwin, SHARE_ADDFILEN, buf);
  290.     }
  291.  
  292.     return(0);
  293. }
  294.  
  295.  
  296. ULONG share_new(struct IClass *cl, Object *obj, struct opSet *msg)
  297. {
  298.     static const struct Hook sharelistdispHook    = { {NULL, NULL}, &sharelistdisp, NULL, NULL };
  299.     static const struct Hook sharelistcompHook    = { {NULL, NULL}, &sharelistcomp, NULL, NULL };
  300.     static const struct Hook sharelistdestHook    = { {NULL, NULL}, &sharelistdest, NULL, NULL };
  301.     static const struct Hook ShareListAppMsgHook  = { {NULL, NULL}, &ShareListAppMsgFunc, NULL, NULL };
  302.  
  303.     struct shdata *data;
  304.     Object *list, *stat, *addbut, *adddirbut, *rembut, *remallbut;
  305.  
  306.     if (obj = (Object *)DoSuperNew(cl, obj,
  307.         MUIA_HelpNode, "sharing",
  308.         MUIA_Window_ID, MAKE_ID('S','H','A','R'),
  309.         MUIA_Window_Title, MSG_SHARE_TITLE,
  310.         MUIA_Window_AppWindow, TRUE,
  311.         WindowContents, VGroup,
  312.             MUIA_HelpNode, "sharing",
  313.             Child, stat = TextObject,
  314.                 TextFrame,
  315.                 MUIA_Background, MUII_TextBack,
  316.                 MUIA_Text_PreParse, "\33c",
  317.             End,
  318.             Child, list = NListviewObject,
  319.                 MUIA_NListview_NList, NListObject,
  320.                     InputListFrame,
  321.                     MUIA_NList_Title, TRUE,
  322.                     MUIA_NList_Format, "BAR, BAR, BAR, BAR, BAR, BAR",
  323.                     MUIA_NList_DisplayHook, &sharelistdispHook,
  324.                     MUIA_NList_CompareHook2, &sharelistcompHook,
  325.                     MUIA_NList_DestructHook, &sharelistdestHook,
  326.                     MUIA_NList_MultiSelect, MUIV_NList_MultiSelect_Default,
  327.                     MUIA_NList_MinColSortable, 0,
  328.                     MUIA_CycleChain, 1,
  329.                 End,
  330.             End,
  331.             Child, HGroup,
  332.                 Child, addbut    = SimpleButton(MSG_SHARE_ADD_GAD         ),
  333.                 Child, adddirbut = SimpleButton(MSG_SHARE_ADDRECURSIVE_GAD),
  334.                 Child, rembut    = SimpleButton(MSG_SHARE_REMOVE_GAD      ),
  335.                 Child, remallbut = SimpleButton(MSG_SHARE_REMOVEALL_GAD   ),
  336.             End,
  337.         End,
  338.         TAG_MORE, msg->ops_AttrList))
  339.     {
  340.         data = INST_DATA(cl,obj);
  341.         data->list = list;
  342.         data->stat = stat;
  343.  
  344.  
  345.         /* Default sort */
  346.  
  347.         DoMethod(list, MUIM_Set, MUIA_NList_TitleMark, 0);
  348.         DoMethod(list, MUIM_NList_Sort3, 0, MUIV_NList_SortTypeAdd_2Values, MUIV_NList_Sort3_SortType_Both);
  349.  
  350.         /* Window notify */
  351.  
  352.         DoMethod(obj, MUIM_Notify, MUIA_Window_CloseRequest, TRUE, gui->iconpanel, 1, PANEL_CLOSESHARE);
  353.  
  354.         /* List notifies */
  355.  
  356.         DoMethod(list, MUIM_Notify, MUIA_NList_DoubleClick, MUIV_EveryTime, obj,  1, SHARE_PLAY);
  357.          DoMethod(list, MUIM_Notify, MUIA_NList_TitleClick,  MUIV_EveryTime, list, 4, MUIM_NList_Sort3, MUIV_TriggerValue, MUIV_NList_SortTypeAdd_2Values, MUIV_NList_Sort3_SortType_Both);
  358.         DoMethod(list, MUIM_Notify, MUIA_NList_TitleClick2, MUIV_EveryTime, list, 4, MUIM_NList_Sort3, MUIV_TriggerValue, MUIV_NList_SortTypeAdd_2Values, MUIV_NList_Sort3_SortType_2);
  359.         DoMethod(list, MUIM_Notify, MUIA_NList_SortType,    MUIV_EveryTime, list, 3, MUIM_Set, MUIA_NList_TitleMark,  MUIV_TriggerValue);
  360.         DoMethod(list, MUIM_Notify, MUIA_NList_SortType2,   MUIV_EveryTime, list, 3, MUIM_Set, MUIA_NList_TitleMark2, MUIV_TriggerValue);
  361.         DoMethod(list, MUIM_Notify, MUIA_AppMessage,        MUIV_EveryTime, list, 3, MUIM_CallHook, &ShareListAppMsgHook, MUIV_TriggerValue);
  362.  
  363.         /* Button notifies */
  364.  
  365.         DoMethod(addbut,    MUIM_Notify, MUIA_Pressed, FALSE, obj, 1, SHARE_ADD      );
  366.         DoMethod(adddirbut, MUIM_Notify, MUIA_Pressed, FALSE, obj, 1, SHARE_ADDDIR   );
  367.         DoMethod(rembut,    MUIM_Notify, MUIA_Pressed, FALSE, obj, 2, SHARE_REMOVE, 0);
  368.         DoMethod(remallbut, MUIM_Notify, MUIA_Pressed, FALSE, obj, 2, SHARE_REMOVE, 1);
  369.  
  370.         /* Allocate file requesters */
  371.  
  372.         FReqAddFiles = AllocAslRequestTags(ASL_FileRequest,
  373.             ASLFR_TitleText, MSG_SHARE_ADD_REQ,
  374.             ASLFR_InitialPattern, (ULONG)"#?.mp(2|3)",
  375.             ASLFR_InitialDrawer, (ULONG)prf->dlpath,
  376.             ASLFR_DoPatterns, TRUE,
  377.             ASLFR_DoMultiSelect, TRUE,
  378.             ASLFR_RejectIcons, TRUE,
  379.             TAG_DONE);
  380.         FReqAddDir = AllocAslRequestTags(ASL_FileRequest,
  381.             ASLFR_TitleText, MSG_SHARE_ADDDIR_REQ,
  382.             ASLFR_InitialDrawer, (ULONG)prf->dlpath,
  383.             ASLFR_DrawersOnly, TRUE,
  384.             TAG_DONE);
  385.         FReqLibrary = AllocAslRequestTags(ASL_FileRequest,
  386.             ASLFR_InitialFile, "Amster.shares",
  387.             ASLFR_InitialDrawer, "PROGDIR:",
  388.             ASLFR_RejectIcons, TRUE,
  389.             TAG_DONE);
  390.  
  391.         return((ULONG)obj);
  392.     }
  393.     return(0);
  394. }
  395.  
  396.  
  397. /* Private functions */
  398.  
  399.  
  400. void add_filename(struct shdata *data, char *fname)
  401. {
  402.     sharedata sd;
  403.     struct FileInfoBlock *fib;
  404.     BPTR lock;
  405.  
  406.     if (!(fib = AllocDosObject(DOS_FIB, NULL))) return;
  407.  
  408.     if (sd = malloc(sizeof(_sharedata))) {
  409.         memset(sd, 0, sizeof(_sharedata));
  410.  
  411.         strcpy(sd->title, fname);
  412.         if (lock = Lock(fname, ACCESS_READ)) {
  413.             if (Examine(lock, fib)) {
  414.                 sd->size = fib->fib_Size;
  415.                 if (NameFromLock(lock, sd->title, 255)) {
  416.                     if (fib->fib_DirEntryType < 0) add_shareinfo(data, sd, lock);
  417.                     else if (fib->fib_DirEntryType > 0) {
  418.                         add_recursive(data, sd, lock, sd->title);
  419.                         UnLock(lock);
  420.                     }
  421.                 }
  422.                 else UnLock(lock);
  423.             }
  424.         }
  425.     }
  426.  
  427.     FreeDosObject(DOS_FIB, fib);
  428. }
  429.  
  430.  
  431. void add_file(struct shdata *data, song sdl, char *fname)
  432. {
  433.     sharedata sd;
  434.     struct FileInfoBlock *fib;
  435.     BPTR lock;
  436.  
  437.     if (sd = malloc(sizeof(_sharedata))) {
  438.         memset(sd, 0, sizeof(_sharedata));
  439.  
  440.         if (fib = AllocDosObject(DOS_FIB, NULL)) {
  441.             if (lock = Lock(fname, ACCESS_READ)) {
  442.                 NameFromLock(lock, sd->title, 255);
  443.                 UnLock(lock);
  444.             }
  445.             FreeDosObject(DOS_FIB, fib);
  446.         }
  447.  
  448.         if (!sd->title) strcpy(sd->title, fname);
  449.         strncpy(sd->md5, sdl->md5, 32);
  450.         sd->size    = sdl->size;
  451.         sd->bitrate = sdl->bit;
  452.         sd->freq    = sdl->freq;
  453.         sd->time    = sdl->time;
  454.  
  455.         DoMethod(data->list, MUIM_NList_InsertSingle, sd, MUIV_NList_Insert_Sorted);
  456.         numsongs++; numbytes += sd->size;
  457.         sharechanged = TRUE;
  458.         update_stat(data);
  459.         if (gui_onlinestate == ONLINE) nap_notifyshare(sd);
  460.     }
  461.  
  462.     return;
  463. }
  464.  
  465.  
  466. void add_shares(struct shdata *data)
  467. {
  468.     sharedata sd;
  469.     BPTR lock;
  470.     struct FileInfoBlock *fib;
  471.     int i;
  472.     u_long win;
  473.  
  474.     get(gui->shwin, MUIA_Window_Window, &win);
  475.  
  476.     if (FReqAddFiles) {
  477.         if (AslRequestTags(FReqAddFiles, ASLFR_Window, win, TAG_DONE)) {
  478.                 if (fib = AllocDosObject(DOS_FIB, NULL)) {
  479.                     for (i=0; i<FReqAddFiles->fr_NumArgs; i++) {
  480.                         if (sd = malloc(sizeof(_sharedata))) {
  481.                             memset(sd, 0, sizeof(_sharedata));
  482.                             strcpy(sd->title, FReqAddFiles->fr_Drawer);
  483.                             AddPart(sd->title, FReqAddFiles->fr_ArgList[i].wa_Name, 255);
  484.                             if (lock = Lock(sd->title, ACCESS_READ)) {
  485.                                 if (Examine(lock, fib)) {
  486.                                     sd->size = fib->fib_Size;
  487.                                     if (NameFromLock(lock, sd->title, 255)) {
  488.                                         if (fib->fib_DirEntryType < 0) add_shareinfo(data, sd, lock);
  489.                                         else if (fib->fib_DirEntryType > 0) {
  490.                                             add_recursive(data, sd, lock, sd->title);
  491.                                             UnLock(lock);
  492.                                         }
  493.                                     }
  494.                                     else UnLock(lock);
  495.                                 }
  496.                             }
  497.                         }
  498.                     }
  499.                     FreeDosObject(DOS_FIB, fib);
  500.                 }
  501.         }
  502.         if (sharefailed) {
  503.             MUI_Request(gui->app, gui->shwin, 0L,
  504.                 (char *)MSG_ERROR_TITLE,
  505.                 (char *)MSG_OK_GAD,
  506.                 (char *)MSG_SHARE_ADDFAILED);
  507.             sharefailed = FALSE;
  508.         }
  509.     }
  510. }
  511.  
  512.  
  513. void add_directory(struct shdata *data)
  514. {
  515.     sharedata sd;
  516.     BPTR lock;
  517.     struct FileInfoBlock *fib;
  518.     u_long win;
  519.  
  520.     get(gui->shwin, MUIA_Window_Window, &win);
  521.  
  522.     if (FReqAddDir) {
  523.         if (AslRequestTags(FReqAddDir, ASLFR_Window, win, TAG_DONE)) {
  524.                 if (fib = AllocDosObject(DOS_FIB, NULL)) {
  525.                     if (sd = malloc(sizeof(_sharedata))) {
  526.                         memset(sd, 0, sizeof(_sharedata));
  527.                         strcpy(sd->title, FReqAddDir->fr_Drawer);
  528.                         if (lock = Lock(sd->title, ACCESS_READ)) {
  529.                             if (Examine(lock, fib)) {
  530.                                 sd->size = fib->fib_Size;
  531.                                 if (NameFromLock(lock, sd->title, 255)) {
  532.                                     if (fib->fib_DirEntryType > 0) {
  533.                                         add_recursive(data, sd, lock, sd->title);
  534.                                         UnLock(lock);
  535.                                     }
  536.                                 }
  537.                                 else UnLock(lock);
  538.                             }
  539.                         }
  540.                     }
  541.                     FreeDosObject(DOS_FIB, fib);
  542.                 }
  543.         }
  544.         if (sharefailed) {
  545.             MUI_Request(gui->app, gui->shwin, 0L,
  546.                 (char *)MSG_ERROR_TITLE,
  547.                 (char *)MSG_OK_GAD,
  548.                 (char *)MSG_SHARE_ADDFAILED);
  549.             sharefailed = FALSE;
  550.         }
  551.     }
  552. }
  553.  
  554.  
  555. void add_recursive(struct shdata *data, sharedata sd, BPTR dirlock, const char *dirname)
  556. {
  557.     ULONG namelen;
  558.     long len;
  559.     struct ExAllControl *eac;
  560.     struct ExAllData *ead;
  561.     APTR eadata;
  562.     BOOL more;
  563.     char *name;
  564.     BPTR lock;
  565.     struct FileInfoBlock *fib;
  566.     const long buffersize = 4096;
  567.  
  568.     if (dirlock) {
  569.         namelen = strlen(dirname);
  570.         eac = AllocDosObject(DOS_EXALLCONTROL, NULL);
  571.         if (eac) {
  572.             eac->eac_LastKey = 0;
  573.             eac->eac_MatchString = 0;
  574.             eac->eac_MatchFunc = 0;
  575.             eadata = malloc(buffersize);
  576.             if (eadata) {
  577.                 do {
  578.                     more = ExAll(dirlock, eadata, buffersize, ED_TYPE, eac);
  579.                     if (eac->eac_Entries > 0) {
  580.                         ead = eadata;
  581.                         do {
  582.                             len = namelen + strlen(ead->ed_Name);
  583.                             name = (char *)malloc(len+5);
  584.                             if (name) {
  585.                                 strcpy(name, dirname);
  586.                                 if (AddPart(name, ead->ed_Name, len+5)) {
  587.                                     if (ead->ed_Type > 0) {
  588.                                         lock = Lock(name, ACCESS_READ);
  589.                                         if (lock) {
  590.                                             add_recursive(data, sd, lock, name);
  591.                                             UnLock(lock);
  592.                                         }
  593.                                     }
  594.                                     else if (ead->ed_Type < 0) {
  595.                                         if (sd = malloc(sizeof(_sharedata))) {
  596.                                             memset(sd, 0, sizeof(_sharedata));
  597.                                             strcpy(sd->title, name);
  598.                                             if (fib = AllocDosObject(DOS_FIB, NULL)) {
  599.                                                 lock = Lock(name, ACCESS_READ);
  600.                                                 if (lock) {
  601.                                                     if (Examine(lock, fib)) {
  602.                                                         sd->size = fib->fib_Size;
  603.                                                         add_shareinfo(data, sd, lock);
  604.                                                     }
  605.                                                 }
  606.                                                 FreeDosObject(DOS_FIB, fib);
  607.                                             }
  608.                                         }
  609.                                     }
  610.                                 }
  611.                                 free(name);
  612.                             }
  613.                             ead = ead->ed_Next;
  614.                         } while(ead);
  615.                     }
  616.                     if ((!more) && (IoErr() != ERROR_NO_MORE_ENTRIES)) break;
  617.                     if (eac->eac_Entries == 0) continue;
  618.                 } while (more);
  619.                 free(eadata);
  620.             }
  621.             FreeDosObject(DOS_EXALLCONTROL, eac);
  622.         }
  623.     }
  624. }
  625.  
  626.  
  627. void add_shareinfo(struct shdata *data, sharedata sd, BPTR lock)
  628. {
  629.     unsigned int m_id, m_layer, m_bit, m_freq, m_mode;
  630.     APTR buffer;
  631.     BPTR fh;
  632.     int i=0, j=0, len, total, col;
  633.     long vbrbytes = 0, vbrframes = 0, vbr = 0;
  634.     BOOL header = FALSE;
  635.     int badhdr[10];
  636.     char *suffix;
  637.  
  638.     sharedata sdtmp;
  639.     ULONG tmp;
  640.  
  641.     md5_state_t state;
  642.     md5_byte_t digest[16];
  643.     int di;
  644.  
  645.     /*    MP3 information source:
  646.         http://mp3tech.free.fr/programmers/frame_header.html
  647.     */
  648.  
  649.     int mp3_bitrates[14][6] = {
  650.     /*   V1L1,V1L2,V1L3,V2L1,V2L2,V2L3   */
  651.         {  32,  32,  32,  32,   8,   8 },
  652.         {  64,  48,  40,  48,  16,  16 },
  653.         {  96,  56,  48,  56,  24,  24 },
  654.         { 128,  64,  56,  64,  32,  32 },
  655.         { 160,  80,  64,  80,  40,  40 },
  656.         { 192,  96,  80,  96,  48,  48 },
  657.         { 224, 112,  96, 112,  56,  56 },
  658.         { 256, 128, 112, 128,  64,  64 },
  659.         { 288, 160, 128, 144,  80,  80 },
  660.         { 320, 192, 160, 160,  96,  96 },
  661.         { 352, 224, 192, 176, 112, 112 },
  662.         { 384, 256, 224, 192, 128, 128 },
  663.         { 416, 320, 256, 224, 144, 144 },
  664.         { 448, 384, 320, 256, 160, 160 }
  665.     };
  666. /*    V1 = MPEG Version 1
  667.     V2 = MPEG Version 2 and Version 2.5
  668.     L1 = Layer I
  669.     L2 = Layer II
  670.     L3 = Layer III
  671. */
  672.  
  673.     int mp3_frequencies[3][3] = {
  674.     /*    MPEG1, MPEG2, MPEG2.5    */
  675.         { 44100, 22050, 11025 },
  676.         { 48000, 24000, 12000 },
  677.         { 32000, 16000,  8000 }
  678.     };
  679.  
  680.     if (IsIn(sd->title, '"') || IsIn(sd->title, '\\')) {
  681.         gui_debugf((char *)MSG_SHARE_ILLEGALCHARS, sd->title);
  682.         sharefailed = TRUE;
  683.         UnLock(lock);
  684.         return;
  685.     }
  686.  
  687.     suffix = sd->title + strlen(sd->title) - 4;
  688.     if (stricmp(suffix, ".mp3") != 0 && stricmp(suffix, ".mp2") != 0) {
  689.         gui_debugf((char *)MSG_SHARE_INVALIDEXTENSION, sd->title);
  690.         sharefailed = TRUE;
  691.         UnLock(lock);
  692.         return;
  693.     }
  694.  
  695.     GetAttr(MUIA_NList_Entries, data->list, &tmp);
  696.     total = tmp;
  697.  
  698.     while (i < total) {
  699.         DoMethod(data->list, MUIM_NList_GetEntry, i, &sdtmp);
  700.         if (sdtmp) if (strcmp(sd->title, sdtmp->title) == 0) {
  701.             gui_debugf((char *)MSG_SHARE_EXISTS, sd->title);
  702.             sharefailed = TRUE;
  703.             UnLock(lock);
  704.             return;
  705.         }
  706.         i++;
  707.     }
  708.  
  709.     if (fh = OpenFromLock(lock)) {
  710.         if (buffer = AllocMem(300032, MEMF_ANY)) {
  711.  
  712.             md5_init(&state);
  713.  
  714.             len = Read(fh, buffer, 300032);
  715.             if (len > 0) {
  716.  
  717.                 md5_append(&state, (const md5_byte_t *)buffer, len);
  718.                 md5_finish(&state, digest);
  719.                 for (di = 0; di < 16; ++di)
  720.                     sprintf(sd->md5+di*2, "%02x", digest[di]);
  721.  
  722.                 /* Only check first 128 kB for valid MP3 header */
  723.                 if (len > 128*1024) len = 128*1024;
  724.  
  725.                 /* Check for VBR */
  726.                 for (i=0; i<len; i++) {
  727.                     if (*((unsigned char *)buffer+i) == 'X')
  728.                         if (*((unsigned char *)buffer+i+1) == 'i')
  729.                             if (*((unsigned char *)buffer+i+2) == 'n')
  730.                                 if (*((unsigned char *)buffer+i+3) == 'g') {
  731.                                     j = i + 7;
  732.                                     if ((*((char *)buffer+j) & 1) && ((*((char *)buffer+j) & 2) >> 1)) {
  733.                                         j++;
  734.                                         vbrframes = *((unsigned long *)buffer+j/4);
  735.                                         vbrbytes = *((unsigned long *)buffer+(j+4)/4);
  736.                                         j += 7;
  737.                                     }
  738.                                     if (vbrframes > 0 && vbrbytes > 0) vbr = ((vbrbytes / vbrframes) * 1000) / 3265;
  739.                                     break;
  740.                                 }
  741.                 }
  742.  
  743.                 i = j;
  744.                 if (stcd_i(buffer, badhdr) == 8 && i < 417) i = 417;
  745.                 /* Work-around for "MpegDJ Encoder" bug */
  746.  
  747.                 while (!header && i<len-3) {
  748.                     /* Seek until synchronization is found (%11111111.111xxxxx) */
  749.                     if (*((unsigned char *)buffer+i) == 255) {
  750.                         if (*((unsigned char *)buffer+i+1) >= 224) {
  751.  
  752.                             /*    MPEG Audio version ID
  753.                                 00 - MPEG Version 2.5 (later extension of MPEG 2)
  754.                                 01 - reserved
  755.                                 10 - MPEG Version 2 (ISO/IEC 13818-3)
  756.                                 11 - MPEG Version 1 (ISO/IEC 11172-3)
  757.                             */
  758.  
  759.                             m_id = 3 - ((*((char *)buffer+i+1) & 24)>>3);
  760.                             if (m_id == 3) m_id = 1;
  761.  
  762.                             /*    Layer description
  763.                                 00 - reserved
  764.                                 01 - Layer III
  765.                                 10 - Layer II
  766.                                 11 - Layer I
  767.                             */
  768.  
  769.                             m_layer = 4 - ((*((char *)buffer+i+1) & (2+4))>>1);
  770.                             m_bit   =      (*((char *)buffer+i+2) & (16+32+64+128))>>4;
  771.                             m_freq  =      (*((char *)buffer+i+2) & (4+8))>>2;
  772.  
  773.                             /*    Channel Mode
  774.                                 00 - Stereo
  775.                                 01 - Joint stereo (Stereo)
  776.                                 10 - Dual channel (2 mono channels)
  777.                                 11 - Single channel (Mono)
  778.                             */
  779.  
  780.                             m_mode  =      (*((char *)buffer+i+3) & (64+128))>>6;
  781.  
  782.                             col = m_layer-1;
  783.                             if (m_id == 1) col=col+3;
  784.  
  785.                             if (m_bit>0 && m_bit<15 && m_freq < 3 && m_layer < 4 && m_id != 2) {
  786.  
  787.                                 header = TRUE;
  788.  
  789.                                 sd->freq = mp3_frequencies[m_freq][m_id];
  790.                                 if (vbr > 0) sd->bitrate = vbr;
  791.                                 else sd->bitrate = mp3_bitrates[m_bit-1][col];
  792.  
  793.                                 if (m_layer == 2) { /* Sanity checks */
  794.                                     if ((sd->bitrate == 32 || sd->bitrate == 48 || sd->bitrate == 46 || sd->bitrate == 80) && m_mode != 3) header = FALSE;
  795.                                     if ((sd->bitrate == 224 || sd->bitrate == 256 || sd->bitrate == 320 || sd->bitrate == 384) && m_mode == 3) header = FALSE;
  796.                                 }
  797.  
  798.                                 sd->time = (sd->size-i)/(sd->bitrate*125);
  799.                                 /* 'i' is the length of ID3v2 tag. ID3v1 size is always 128 bytes,
  800.                                    so it's not worth the overhead to check for this.
  801.                                    128 bytes of a 128 kbps MP3 = 0.000008 seconds! */
  802.                             }
  803.                         }
  804.                     }
  805.                     i++;
  806.                 }
  807.             }
  808.             FreeMem(buffer, 300032);
  809.         }
  810.         Close(fh);
  811.         if (header) {
  812.             DoMethod(data->list, MUIM_NList_InsertSingle, sd, MUIV_NList_Insert_Sorted);
  813.             numsongs++; numbytes += sd->size;
  814.             sharechanged = TRUE;
  815.             update_stat(data);
  816.             if (gui_onlinestate == ONLINE) nap_notifyshare(sd);
  817.         }
  818.         else {
  819.             gui_debugf((char *)MSG_SHARE_ADDERROR, sd->title, sd->size, sd->bitrate, sd->freq);
  820.             sharefailed = TRUE;
  821.         }
  822.     }
  823.     else UnLock(lock);
  824.  
  825. }
  826.  
  827.  
  828. void notify_shares(struct shdata *data)
  829. {
  830.     sharedata sd;
  831.     u_long tmp;
  832.     int i, total;
  833.  
  834.     if (gui_onlinestate < LOGGING_IN) return;
  835.  
  836.     GetAttr(MUIA_NList_Entries, data->list, &tmp);
  837.     total = tmp;
  838.  
  839.     if (total > 0) {
  840.         gui_stat((char *)MSG_STATUS2_NOTIFYALL);
  841.         for (i=0; i<total; i++) {
  842.             DoMethod(data->list, MUIM_NList_GetEntry, i, &sd);
  843.             if (!sd) break;
  844.             nap_notifyshare(sd);
  845.         }
  846.     }
  847. }
  848.  
  849.  
  850. void remove_shares(struct shdata *data, long t)
  851. {
  852.     sharedata sd;
  853.     u_long tmp;
  854.     int total;
  855.  
  856.     GetAttr(MUIA_NList_Entries, data->list, &tmp);
  857.     total = tmp;
  858.  
  859.     if (total == 0) return;
  860.  
  861.     switch(t) {
  862.         case 0: /* Remove marked */
  863.             set(data->list, MUIA_NList_Quiet, MUIV_NList_Quiet_Visual);
  864.             DoMethod(data->list, MUIM_NList_Remove, MUIV_NList_Remove_Selected);
  865.             update_stat(data);
  866.             set(data->list,MUIA_NList_Quiet, MUIV_NList_Quiet_None);
  867.             break;
  868.         case 1: /* Remove all */
  869.             set(data->list, MUIA_NList_Quiet, MUIV_NList_Quiet_Visual);
  870.             for (;;) {
  871.                 DoMethod(data->list, MUIM_NList_GetEntry, 0, &sd);
  872.                 if (!sd) break;
  873.                 DoMethod(data->list, MUIM_NList_Remove, MUIV_NList_Remove_First);
  874.             }
  875.             update_stat(data);
  876.             set(data->list, MUIA_NList_Quiet, MUIV_NList_Quiet_None);
  877.             break;
  878.     }
  879.     sharechanged = TRUE;
  880. }
  881.  
  882.  
  883. void save_shares(struct shdata *data)
  884. {
  885.     sharedata sd;
  886.     int i;
  887.     BPTR fh;
  888.     char buf[512], *tmp;
  889.  
  890.     strcpy(buf, FReqLibrary->fr_Drawer);
  891.     AddPart(buf, FReqLibrary->fr_File, 511);
  892.  
  893.     fh = Open(buf, MODE_NEWFILE);
  894.     if (!fh) return;
  895.  
  896.     for (i=0; ; i++) {
  897.         DoMethod(data->list, MUIM_NList_GetEntry, i, &sd);
  898.         if (!sd) break;
  899.         tmp = strrep(sd->title, "\"", "*\"");
  900.         sprintf(buf, "\"%s\" %s %ld %ld %ld %ld REQCOUNT %ld\n", tmp, sd->md5, sd->size, sd->bitrate, sd->freq, sd->time, sd->reqcount);
  901.         free(tmp);
  902.         Write(fh, buf, strlen(buf)); /* Should be buffered, check FWrite */
  903.     }
  904.  
  905.     Close(fh);
  906.     sharechanged = FALSE;
  907. }
  908.  
  909.  
  910. void save_shares_as(struct shdata *data)
  911. {
  912.     u_long win;
  913.  
  914.     get(gui->win, MUIA_Window_Window, &win);
  915.     if (FReqLibrary) {
  916.         if (AslRequestTags(FReqLibrary,
  917.             ASLFR_Window, win,
  918.             ASLFR_TitleText, MSG_SHARE_SAVEAS,
  919.             ASLFR_DoSaveMode, TRUE,
  920.             TAG_DONE)) {
  921.                     save_shares(data);
  922.         }
  923.     }
  924. }
  925.  
  926.  
  927. void load_shares(struct shdata *data)
  928. {
  929.     sharedata sd;
  930.     int line = 0;
  931.     BPTR fh;
  932.     char buf[512], sharefile[512];
  933.     LONG argarray[] = { NULL, NULL, NULL, NULL, NULL, NULL, NULL };
  934.     UBYTE *argstr = "PATH/A,MD5/A,SIZE/A/N,BITRATE/A/N,FREQUENCY/A/N,TIME/A/N,REQCOUNT/K/N";
  935.     struct RDArgs *rdargs;
  936.  
  937.     remove_shares(data, 1);
  938.  
  939.     strcpy(sharefile, FReqLibrary->fr_Drawer);
  940.     AddPart(sharefile, FReqLibrary->fr_File, 511);
  941.  
  942.     if (fh = Open(sharefile, MODE_OLDFILE)) {
  943.         set(data->list,MUIA_NList_Quiet, MUIV_NList_Quiet_Visual);
  944.  
  945.         while (FGets(fh, buf, 512)) {
  946.             line++;
  947.             if (rdargs = AllocDosObject(DOS_RDARGS, NULL)) {
  948.                 rdargs->RDA_Buffer = NULL;
  949.                 rdargs->RDA_Source.CS_Buffer = buf;
  950.                 rdargs->RDA_Source.CS_Length = strlen(buf);
  951.                 if (ReadArgs(argstr, argarray, rdargs)) {
  952.  
  953.                     sd = malloc(sizeof(_sharedata));
  954.  
  955.                     strcpy(sd->title,  (char *)argarray[ ARG_PATH     ]);
  956.                     strcpy(sd->md5,    (char *)argarray[ ARG_MD5      ]);
  957.                     sd->size     =   *((long *)argarray[ ARG_SIZE     ]);
  958.                     sd->bitrate  =   *((long *)argarray[ ARG_BITRATE  ]);
  959.                     sd->freq     =   *((long *)argarray[ ARG_FREQ     ]);
  960.                     sd->time     =   *((long *)argarray[ ARG_TIME     ]);
  961.                     if (argarray[ARG_REQCOUNT]) sd->reqcount =   *((long *)argarray[ ARG_REQCOUNT ]);
  962.                     else sd->reqcount = 0;
  963.  
  964.                     DoMethod(data->list, MUIM_NList_InsertSingle, sd, MUIV_NList_Insert_Bottom);
  965.                     numsongs++; numbytes += sd->size;
  966.                     if (gui_onlinestate == ONLINE) nap_notifyshare(sd);
  967.  
  968.                     FreeArgs(rdargs);
  969.                 }
  970.                 else gui_debugf((char *)MSG_PARSE_ERROR, sharefile, line);
  971.                 FreeDosObject(DOS_RDARGS, rdargs);
  972.             }
  973.         }
  974.  
  975.         set(data->list, MUIA_NList_Quiet, MUIV_NList_Quiet_None);
  976.         update_stat(data);
  977.  
  978.         Close(fh);
  979.     }
  980.     sharechanged = FALSE;
  981. }
  982.  
  983.  
  984. void load_shares_as(struct shdata *data)
  985. {
  986.     u_long win;
  987.  
  988.     get(gui->win, MUIA_Window_Window, &win);
  989.     if (FReqLibrary) {
  990.         if (AslRequestTags(FReqLibrary,
  991.             ASLFR_Window, win,
  992.             ASLFR_TitleText, MSG_SHARE_LOADAS,
  993.             TAG_DONE)) {
  994.                     load_shares(data);
  995.         }
  996.     }
  997. }
  998.  
  999.  
  1000. void update_stat(struct shdata *data)
  1001. {
  1002.     static char buf[100], totalsize[8];
  1003.     char descriptor[16];
  1004.     unsigned long number, tempnumber;
  1005.  
  1006.     if (numbytes >= (1024*1024*1024)) {
  1007.         strcpy(descriptor, MSG_SHARE_STAT_GB);
  1008.         tempnumber = numbytes/1024/1024*10/1024;
  1009.         number = tempnumber/10;
  1010.         tempnumber = tempnumber-(number*10);
  1011.         sprintf(totalsize,"%d.%d", number, tempnumber);
  1012.     }
  1013.     else if (numbytes >= (1024*1024)) {
  1014.         strcpy(descriptor, MSG_SHARE_STAT_MB);
  1015.         tempnumber = numbytes/1024*10/1024;
  1016.         number = tempnumber/10;
  1017.         tempnumber = tempnumber-(number*10);
  1018.         sprintf(totalsize, "%d.%d", number, tempnumber);
  1019.     }
  1020.     else {
  1021.         strcpy(descriptor, MSG_SHARE_STAT_KB);
  1022.         number = numbytes/1024;
  1023.         sprintf(totalsize, "%d", number);
  1024.     }
  1025.  
  1026.     sprintf(buf, MSG_SHARE_STAT_TMP, numsongs, totalsize, descriptor);
  1027.     set(data->stat, MUIA_Text_Contents, buf);
  1028. }
  1029.  
  1030.  
  1031. void play_share(struct shdata *data)
  1032. {
  1033.     sharedata sd;
  1034.     char buf[1024], *command;
  1035.  
  1036.     DoMethod(data->list, MUIM_NList_GetEntry, MUIV_NList_GetEntry_Active, &sd);
  1037.     if (sd) {
  1038.         if (prf->scripts[PRFE_PLAYMP3]) {
  1039.             sprintf(buf, "Run <>NIL: %s", prf->scripts[PRFE_PLAYMP3]);
  1040.             command = strrep(buf, "%f", sd->title);
  1041.             Execute(command, 0, 0);
  1042.             free(command);
  1043.         }
  1044.     }
  1045. }
  1046.  
  1047.  
  1048. void upload_req(char *user, char *fname)
  1049. {
  1050.     DoMethod(gui->shwin, SHARE_UPLOAD, user, fname);
  1051. }
  1052.  
  1053.  
  1054. void upload_file_confirm(struct shdata *data, char *user, char *fname)
  1055. /* Continued from upload_req() */
  1056. {
  1057.     sharedata sd;
  1058.     song s;
  1059.     int i=0, total;
  1060.     ULONG tmp;
  1061.     BOOL found = FALSE;
  1062.     char *path;
  1063.  
  1064.     GetAttr(MUIA_NList_Entries, data->list, &tmp);
  1065.     total = tmp;
  1066.  
  1067.     gui_debugf((char *)MSG_SHARE_REQFILE, user, fname);
  1068.  
  1069.     while (i<total && !found) {
  1070.         DoMethod(data->list, MUIM_NList_GetEntry, i, &sd);
  1071.         if (sd) {
  1072.             path = MakeWinPath(sd->title);
  1073.             if (strcmp(path, fname) == 0) found = TRUE;
  1074.             free(path);
  1075.         }
  1076.         i++;
  1077.     }
  1078.  
  1079.     if (!found) {
  1080.         gui_debug((char *)MSG_SHARE_NOTFOUND);
  1081.         return;
  1082.     }
  1083.  
  1084.     s = malloc(sizeof(_song));
  1085.     if (!s) return;
  1086.     memset(s, 0, sizeof(_song));
  1087.  
  1088.     s->title = strdup(sd->title);
  1089.     s->md5 = strdup(sd->md5);
  1090.     s->size = sd->size;
  1091.     s->bit = sd->bitrate;
  1092.     s->freq = sd->freq;
  1093.     s->time = sd->time;
  1094.     s->user = strdup(user);
  1095.     /* At this point we don't know IP and link speed - can't complete the struct */
  1096.  
  1097.     ul_addq(s);
  1098. }
  1099.  
  1100.  
  1101. void update_count(struct shdata *data, char *fname)
  1102. {
  1103.     sharedata sd;
  1104.     int i;
  1105.     long pos;
  1106.  
  1107.     for (i=0; ; i++) {
  1108.         DoMethod(data->list, MUIM_NList_GetEntry, i, &sd);
  1109.         if (!sd) return;
  1110.         if (strcmp(sd->title, fname) == 0) break;
  1111.     }
  1112.  
  1113.     /* Update statistics (count) */
  1114.     sd->reqcount++;
  1115.     sharechanged = TRUE;
  1116.  
  1117.     pos = MUIV_NList_GetPos_Start;
  1118.     DoMethod(data->list, MUIM_NList_GetPos, sd, &pos);
  1119.     DoMethod(data->list, MUIM_NList_Redraw, pos);
  1120. }
  1121.  
  1122.  
  1123. void nap_notifyshare(sharedata sd)
  1124. {
  1125.     char *path, *suffix;
  1126.  
  1127.     /* In case invalid files were added manually or with an earlier version */
  1128.     if (IsIn(sd->title, '"') || IsIn(sd->title, '\\')) {
  1129.         gui_debugf((char *)MSG_SHARE_ILLEGALCHARS, sd->title);
  1130.         return;
  1131.     }
  1132.  
  1133.     suffix = sd->title + strlen(sd->title) - 4;
  1134.     if (stricmp(suffix, ".mp3") != 0 && stricmp(suffix, ".mp2") != 0) {
  1135.         gui_debugf((char *)MSG_SHARE_INVALIDEXTENSION, sd->title);
  1136.         return;
  1137.     }
  1138.  
  1139.     path = MakeWinPath(sd->title);
  1140.     sprintf(nap_buf, "\"%s\" %s %ld %ld %ld %ld", path, sd->md5, sd->size, sd->bitrate, sd->freq, sd->time);
  1141.     free(path);
  1142.     nap_send(NAPC_NOTIFYSHARE);
  1143. }
  1144.  
  1145.  
  1146. char *strrep(char *str1, char *old_str, char *new_str)
  1147. {
  1148.     char *str;
  1149.     int len, i;
  1150.  
  1151.     if (!(str = malloc(1024))) return str1;
  1152.     str[0] = '\0';
  1153.  
  1154.     for (i=0; i<strlen(str1); i++) {
  1155.         if (strncmp(str1+i, old_str, strlen(old_str)) == 0) {
  1156.             strcat(str, new_str);
  1157.             i += strlen(old_str)-1;
  1158.         }
  1159.         else {
  1160.             len = strlen(str);
  1161.             str[len] = str1[i];
  1162.             str[len+1] = '\0';
  1163.         }
  1164.     }
  1165.  
  1166.     return str;
  1167. }
  1168.  
  1169.  
  1170. char *MakeWinPath(char *AmigaPath)
  1171. /* PRE: The AmigaPath must contain max. 1 colon */
  1172. {
  1173.     char *WinPath;
  1174.     int i, j;
  1175.  
  1176.     if (!(WinPath = malloc(strlen(AmigaPath)+2))) return AmigaPath;
  1177.  
  1178.     for (i=0, j=0; i<strlen(AmigaPath); i++, j++) {
  1179.         if (AmigaPath[i] == '/') WinPath[j] = '\\';
  1180.         else if (AmigaPath[i] == ':') {
  1181.             WinPath[j++] = ':';
  1182.             WinPath[j] = '\\';
  1183.         }
  1184.         else WinPath[j] = AmigaPath[i];
  1185.     }
  1186.     WinPath[j] = '\0';
  1187.  
  1188.     return WinPath;
  1189. }
  1190.  
  1191.  
  1192. BOOL IsIn(char *string, char c)
  1193. {
  1194.     int i;
  1195.  
  1196.     for (i=0; i<strlen(string); i++)
  1197.         if (string[i] == c) return TRUE;
  1198.  
  1199.     return FALSE;
  1200. }
  1201.